package untils

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"order_srv/basic/config"
)

// 百度地图地理编码API响应结构
type GeocodingResponse struct {
	Status int `json:"status"`
	Result struct {
		Location struct {
			Lng float64 `json:"lng"` // 经度
			Lat float64 `json:"lat"` // 纬度
		} `json:"location"`
		FormattedAddress string `json:"formatted_address"` // 格式化地址
		Precise          int    `json:"precise"`           // 位置的精确程度
		Confidence       int    `json:"confidence"`        // 可信度
		Level            string `json:"level"`             // 地址类型
	} `json:"result"`
}

// 地址转经纬度函数
func GetCoordinates(address string) (GeocodingResponse, error) {
	// 对地址进行URL编码
	encodedAddress := url.QueryEscape(address)
	if encodedAddress == "" {
		return GeocodingResponse{}, errors.New("无效的地址")
	}

	// 构建API请求URL
	apiURL := fmt.Sprintf(
		config.AppCong.Coordinate,
		encodedAddress,
		config.AppCong.MapAccessKeyID,
	)

	// 发送HTTP GET请求
	resp, err := http.Get(apiURL)
	if err != nil {
		return GeocodingResponse{}, errors.New("请求百度地图API失败")
	}
	defer resp.Body.Close()

	// 检查HTTP响应状态
	if resp.StatusCode != http.StatusOK {
		return GeocodingResponse{}, errors.New("api请求失败")
	}

	// 解析JSON响应
	var geocodingResp GeocodingResponse
	decoder := json.NewDecoder(resp.Body)
	if err = decoder.Decode(&geocodingResp); err != nil {
		return GeocodingResponse{}, errors.New("解析坐标失败" + err.Error())
	}

	// 检查API返回状态
	if geocodingResp.Status != 0 {
		return GeocodingResponse{}, errors.New(fmt.Sprintf("地理编码失败，错误代码: %d", geocodingResp.Status))
	}
	fmt.Println(geocodingResp)
	// 返回解析结果
	return geocodingResp, err
}

type Location struct {
	Lng float64 `json:"lng"` // 经度
	Lat float64 `json:"lat"` // 纬度
}

// 百度地图路径规划API响应结构
type RouteResponse struct {
	Status int `json:"status"`
	Result struct {
		Routes []struct {
			Distance    int      `json:"distance"`    // 距离，单位：米
			Duration    int      `json:"duration"`    // 时间，单位：秒
			Origin      Location `json:"origin"`      // 起点坐标
			Destination Location `json:"destination"` // 终点坐标
			Steps       []struct {
				Instruction string `json:"instruction"` // 行驶指示
				Distance    int    `json:"distance"`    // 该段距离
				Duration    int    `json:"duration"`    // 该段时间
				Path        string `json:"path"`        // 该段路径坐标点
			} `json:"steps"` // 路径步骤
		} `json:"routes"` // 推荐路线列表
	} `json:"result"`
}

// 获取推荐路径及距离
// origin和destination格式为"纬度,经度"
// ak为百度地图API密钥
// tactics为出行策略：0-推荐路线, 1-最短时间, 2-最短距离, 3-躲避拥堵
func GetRoute(origin, destination string, tactics int) (*RouteResponse, error) {
	// 构建API请求URL
	baseURL := config.AppCong.RecommendWay
	params := url.Values{}
	params.Add("ak", config.AppCong.MapAccessKeyID)
	params.Add("origin", origin)
	params.Add("destination", destination)
	params.Add("tactics", fmt.Sprintf("%d", tactics))
	params.Add("output", "json")

	urlStr := fmt.Sprintf("%s?%s", baseURL, params.Encode())

	// 发送请求
	resp, err := http.Get(urlStr)
	if err != nil {
		return nil, fmt.Errorf("请求百度地图API失败: %v", err)
	}
	defer resp.Body.Close()

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("API请求失败，状态码: %d", resp.StatusCode)
	}

	// 解析JSON响应
	var routeResp RouteResponse
	decoder := json.NewDecoder(resp.Body)
	if err := decoder.Decode(&routeResp); err != nil {
		return nil, fmt.Errorf("解析响应失败: %v", err)
	}

	// 检查API返回状态
	if routeResp.Status != 0 {
		return nil, fmt.Errorf("路径规划失败，错误代码: %d", routeResp.Status)
	}

	if len(routeResp.Result.Routes) == 0 {
		return nil, fmt.Errorf("未找到可用路线")
	}
	return &routeResp, nil
}

// 经纬度获取地址信息
func MapInfo(lat, lnt string) (MapGetLocResult, error) {
	locInfoUrl := fmt.Sprintf("https://api.map.baidu.com/reverse_geocoding/v3/?ak=%v&extensions_poi=1&entire_poi=1&sort_strategy=distance&output=json&coordtype=bd09ll&location=%v,%v", config.AppCong.MapAccessKeyID, lat, lnt)
	get, err := http.Get(locInfoUrl)
	if err != nil {
		return MapGetLocResult{}, err
	}
	//	get.Body
	body, err := io.ReadAll(get.Body)
	if err != nil {
		return MapGetLocResult{}, err
	}
	var data MapGetLocResult
	_ = json.Unmarshal(body, &data)
	return data, nil
}

type MapGetLocResult struct {
	Status int `json:"status"`
	Result struct {
		Location struct {
			Lng float64 `json:"lng"`
			Lat float64 `json:"lat"`
		} `json:"location"`
		FormattedAddress string `json:"formatted_address"`
		Edz              struct {
			Name string `json:"name"`
		} `json:"edz"`
		Business     string `json:"business"`
		BusinessInfo []struct {
			Name     string `json:"name"`
			Location struct {
				Lng float64 `json:"lng"`
				Lat float64 `json:"lat"`
			} `json:"location"`
			Adcode    int    `json:"adcode"`
			Distance  int    `json:"distance"`
			Direction string `json:"direction"`
		} `json:"business_info"`
		AddressComponent struct {
			Country         string `json:"country"`
			CountryCode     int    `json:"country_code"`
			CountryCodeIso  string `json:"country_code_iso"`
			CountryCodeIso2 string `json:"country_code_iso2"`
			Province        string `json:"province"`
			City            string `json:"city"`
			CityLevel       int    `json:"city_level"`
			District        string `json:"district"`
			Town            string `json:"town"`
			TownCode        string `json:"town_code"`
			Distance        string `json:"distance"`
			Direction       string `json:"direction"`
			Adcode          string `json:"adcode"`
			Street          string `json:"street"`
			StreetNumber    string `json:"street_number"`
		} `json:"addressComponent"`
		Pois                []interface{} `json:"pois"`
		Roads               []interface{} `json:"roads"`
		PoiRegions          []interface{} `json:"poiRegions"`
		SematicDescription  string        `json:"sematic_description"`
		FormattedAddressPoi string        `json:"formatted_address_poi"`
		CityCode            int           `json:"cityCode"`
	} `json:"result"`
}

// 获取用户当前位置
func GetUserNowLoc(lat, lnt string) (UserNowLocation, error) {
	locUrl := fmt.Sprintf("https://api.map.baidu.com/reverse_geocoding/agent?location=%v,%v&coordtype=bd09ll&demand=我在打车，需要告诉司机我现在的位置&ak=%v", lat, lnt, config.AppCong.MapAccessKeyID)
	get, err := http.Get(locUrl)
	if err != nil {
		return UserNowLocation{}, errors.New("调用失败" + err.Error())
	}
	body, err := io.ReadAll(get.Body)
	if err != nil {
		return UserNowLocation{}, errors.New("读取响应失败" + err.Error())
	}
	var data UserNowLocation
	_ = json.Unmarshal(body, &data)
	return data, nil
}

type UserNowLocation struct {
	Status int `json:"status"`
	Result struct {
		Location struct { // 当前位置经纬度
			Lng float64 `json:"lng"`
			Lat float64 `json:"lat"`
		} `json:"location"`
		AddressComponent struct { //地址信息
			Country      string `json:"country"`
			Province     string `json:"province"`
			City         string `json:"city"`
			CityLevel    int    `json:"city_level"`
			District     string `json:"district"`
			Town         string `json:"town"`
			TownCode     string `json:"town_code"`
			Adcode       string `json:"adcode"`
			Street       string `json:"street"`
			StreetNumber string `json:"street_number"`
		} `json:"addressComponent"`
		BusinessInfo []struct { //站点
			Name     string `json:"name"`
			Location struct {
				Lng float64 `json:"lng"`
				Lat float64 `json:"lat"`
			} `json:"location"`
			Adcode    int    `json:"adcode"`
			Distance  int    `json:"distance"`
			Direction string `json:"direction"`
		} `json:"business_info"`
	}
}
